package org.budo.graph.service.util;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

import org.budo.support.lang.util.ClassLoaderUtil;
import org.budo.support.lang.util.JarInfo;
import org.budo.support.lang.util.StringUtil;
import org.budo.support.slf4j.Slf4j;
import org.slf4j.Logger;
import org.springframework.context.ApplicationContext;

import com.alibaba.druid.support.json.JSONUtils;

/**
 * @author limingwei
 * 
 * @see org.budo.support.lang.util.JarInfo
 */
public class ClassPathUtil {
    private static final Logger log = Slf4j.getLogger();

    private static final String[] ROOT_PACKAGES = { "io", "org", "com", "cn", "java", "javax", "javassist" };

    public static String writeClassPathResponse(ApplicationContext applicationContext, String url) {
        if (StringUtil.contains(url, "class-path.json")) {
            return json();
        }

        return html();
    }

    private static String json() {
        List<JarInfo> jarFiles = new ArrayList<JarInfo>();

        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

        for (String _package : ROOT_PACKAGES) {
            Enumeration<URL> enumeration = ClassLoaderUtil.getResources(classLoader, _package);
            List<URL> urls = Collections.list(enumeration);

            for (URL url : urls) {
                String protocol = url.getProtocol();
                if ("jar".equals(protocol)) {
                    JarInfo jarInfo = JarInfo._jarInfo_2(url);
                    if (null == jarInfo) {
                        log.warn("#47 null jar file, url=" + url);
                    } else {
                        jarFiles.add(jarInfo);
                    }
                    continue;
                }

                if ("file".equals(protocol)) {
                    log.info("#51 protocol=" + protocol + ", url=" + url);
                    continue;
                }

                log.warn("#55 protocol=" + protocol + ", url=" + url);
            }
        }

        return JSONUtils.toJSONString(jarFiles);
    }

    private static String html() {
        try {
            List<String> command = listJars();
            Collections.sort(command);

            int i = 1;
            String result = "<pre>";
            for (String line : command) {
                result += (i++) + ". " + line + "\n";
            }
            result += "</pre>";

            return result;
        } catch (Throwable e) {
            log.error("#30 e=" + e, e);
            return "ERROR";
        }
    }

    private static List<String> listJars() throws IOException {
        List<String> list = new ArrayList<String>();
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();

        for (String _package : ROOT_PACKAGES) {
            Enumeration<URL> enumeration = classLoader.getResources(_package);
            List<URL> urls = Collections.list(enumeration);

            for (URL url : urls) {
                String protocol = url.getProtocol();
                if ("jar".equals(protocol)) {
                    JarInfo jarInfo = JarInfo._jarInfo_2(url);
                    if (null != jarInfo) {
                        String line = jarInfo.getGroupId() + ":" + jarInfo.getArtifactId() + ":" + jarInfo.getVersion() + ":" + jarInfo.getBuildAt();
                        list.add(line);
                    } else {
                        list.add(url + "");
                    }

                    continue;
                }

                log.warn("#32 protocol=" + protocol + ", url=" + url);
            }
        }

        return list;
    }
}